
Thread *customerThreads[100][5];
Condition *customerConditionVariable[100];
int popAmount[100];
int sodaAmount[100];
int foodReportCount[100];
int custPositions[100][4][2];	/*holds the customers' positions in the theater*/
int custsInBathroom[100];
bool inBathroom[100][4];

Lock *customerLock[100];
Condition *headCustomerCondition[100];

struct CustData{
	int groupNum;
	int groupSize;
};
CustData custDataArray[100];

int groupTotal = 0;
	

/*
Shared Data I use:
	ticketClerkLineLock
	ticketClerkState[]
	ticketClerkLineCount[]
	ticketClerkLineCV[]
*/

#include <math.h>





/*prototype*/
void MiniCustomer(int IDNums[3]);

void CustomerAgent(int GroupNum) {	//parameters: size of group, group number
	numberOfCustomers++;
	int groupNum = GroupNum;
	if(groupNum+1 == groupTotal) {
		printf("CUST_TEST: %i\n", groupNum);
		theaterCV->Signal(theaterLock);
		/*CVSignal(theaterCV, theaterLock);*/
	}
	
	customerLock[groupNum] = new Lock("customer lock");
	/*customerLock[groupNum] = LockCreate("customer lock", 13);*/
	customerLock[groupNum]->Acquire();
	/*LockAcquire(customerLock[groupNum]);*/
	
	headCustomerCondition[groupNum] = new Condition("Head Customer Condition");
	/*headCustomerCondition[groupNum]=CVCreate("Head Customer Condition", 23);*/

	/*DATA*/
	/*number assigned to a group, only ever used in print statements*/
	int ID = groupNum;
	
	/*Number of customers in this group*/
	int custSize;

	/*Array holding the states of the individual customers*/
	int customersBusy[5];	/*0 = Free, 1 = Busy, -1 = Not there*/
	
	/*describes when the customer is supposed to find a new, shorter line*/
	bool newLine;
	
	/*describes when the customer is in the lobby after the film (waiting to leave instead of waiting for next film)*/
	bool seenFilm;
	
	/*says if the group has bought tickets*/
	bool hasTickets;

	/*tells if the customers got food*/
	bool hasFood;

	/*says if the customer has found seats*/
	bool seated;
	
	/*total amount owed when ordering something (concessions/tickets)*/
	int myTotal;
	
	/*references to current clerk types (which position they are in the global arrays of clerks)*/
	int myTicketClerk;
	int myFoodClerk;
	int myTicketTaker;

	/*initialize lock*/

	for(int i = 0; i < 5; i++) {
		customerThreads[groupNum][i] = NULL;
	}
	/*initialize condition variable*/
	customerConditionVariable[groupNum] = new Condition("customer CV");
	/*customerConditionVariable[groupNum] = CVCreate("customer CV", 11);*/
	/*initialize threads*/
	
	
	/*Constructor*/
		newLine = false;
		seenFilm = false;
		hasTickets = false;
		hasFood = false;
		seated = false;
		myTotal = 0;

		custsInBathroom[groupNum]=0;
		
		/*initialized to -1 (doesn't have a clerk yet)*/
		myTicketClerk = -1;
		myFoodClerk = -1;
		myTicketTaker = -1;
		
		/*initialize customer array to default values (assuming only the leader exists)*/
		customersBusy[0] = 0;
		for(int i = 1; i < 5; i++) {
			customersBusy[i] = -1;
		}
		/*define how many customers there are (1-5) and set those that exist to 0*/
		custSize = (rand() % 3) + 2;
		

		for(int i = 1; i < custSize; i++) {
			customersBusy[i] = 0;
		}

		/*fills the positions array with -1s since they don't occupy any positions in theater*/
		for(int i = 0; i < 5; i++) {
			for(int j = 0; j < 2; j++) {
				custPositions[groupNum][i][j] = -1;
			}
		}

		printf("Head customer in group %i has entered the theater\n",groupNum);

	int ia[4][3];
	for(int i = 0; i < custSize-1; i++) {	/*custSize should always be (at minimum) 1*/
		customerThreads[groupNum][i] = new Thread("miniCustomer Thread");
		ia[i][0]=groupNum;
		ia[i][1]=i;
		ia[i][2]=custSize;
		customerThreads[groupNum][i]->Fork((VoidFunctionPtr)MiniCustomer,(int)ia[i]);
	}
	
	customerLock[groupNum]->Release();
	/*LockRelease(customerLock[groupNum]);*/

	/*And so it begins...*/

	/*CUSTOMER-TICKET CLERK INTERACTION: GETTING IN LINE*/
	/*
	Shared Data used here:
		ticketClerkLineLock
		ticketClerkState[]
		ticketClerkLineCount[]
		ticketClerkLineConditionVariables[]
	*/

	do{
		/*Look at lines and get in shortest one*/

		
		/*see if there are any empty lines*/
		myTicketClerk = -1;	/*reset this to -1 so that i can correctly check when i've found a line*/
		for(int i = 0; i < ticketClerks; i++) {
			ticketClerkLocks[i]->Acquire();
			/*LockAcquire(ticketClerkLocks[i]);*/
			if(ticketClerkState[i] == available) {
				/*Found ticket clerk that is available (0)*/
				/*Line cannot be shorter so enter line*/
				myTicketClerk = i;
				ticketClerkState[myTicketClerk] = busy;
				ticketClerkLocks[i]->Release();
				/*LockRelease(ticketClerkLocks[i]);*/
				break;
			}
			ticketClerkLocks[i]->Release();
			/*LockRelease(ticketClerkLocks[i]);*/
		}
		ticketClerkLineLock->Acquire();
		/*LockAcquire(ticketClerkLineLock);*/

		/*holds position of shortest line*/
		int shortestTicketLine = -1;
		/*check if I found an empty line*/

		if(myTicketClerk == -1) {
			/*look for shortest line*/
			
			int shortestLineLength = 9999;
			for(int i = 0; i < ticketClerks; i++) {
				if(ticketClerkLineCount[i] == 0 && ticketClerkState[i] == busy)
				{
					shortestTicketLine = i;
					break;
				}
				if(shortestLineLength > ticketClerkLineCount[i] && ticketClerkState[i] == busy) {
					shortestTicketLine = i;
					shortestLineLength = ticketClerkLineCount[i];
				}
			}
			/*must have shortest line at this point*/
			myTicketClerk = shortestTicketLine;
			/*get in that line*/
			ticketClerkLineCount[myTicketClerk]++;	/*increment my line's size*/
			printf("Head customer in group %i is getting in Ticket Clerk line %i\n",groupNum,myTicketClerk);
			ticketClerkLineConditionVariables[myTicketClerk]->Wait(ticketClerkLineLock);	/*puts the thread to sleep and waits for a signal from the ticket clerk when I'm at the front of the line*/
			/*CVWait(ticketClerkLineConditionVariables[myTicketClerk], ticketClerkLineLock);*/
		}
		else{
			ticketClerkLineLock->Release();
			/*LockRelease(ticketClerkLineLock);*/
		}
		if(ticketClerkState[myTicketClerk]==on_break)
		{
			printf("Head customer of group %i sees ticket clerk %i is on break and must find new line\n",groupNum,myTicketClerk);
		}
			

	}while(ticketClerkState[myTicketClerk] == on_break);	/*if clerk goes on break, customer gets broadcast and starts over*/


	/*CUSTOMER-TICKET CLERK INTERACTION: BUYING TICKETS*/
	/*
	Shared Data used here:
		ticketClerkLocks[]
		ticketClerkState[]
		ticketsBeingSold[]
		ticketClerkCV[]
	*/
	ticketClerkLocks[myTicketClerk]->Acquire();
	/*LockAcquire(ticketClerkLocks[myTicketClerk]);*/
	ticketClerkState[myTicketClerk] = busy;


	/*pass number of tickets and wake up clerk*/
	printf("Head customer in group %i is wallking up to ticket clerk %i to buy %i tickets\n",groupNum,myTicketClerk,custSize);
	ticketsBeingSold[myTicketClerk] = custSize;
	/*And now I wait for the clerk's response (asking to be paid)*/
	ticketClerkConditionVariables[myTicketClerk]->Signal(ticketClerkLocks[myTicketClerk]);
	ticketClerkConditionVariables[myTicketClerk]->Wait(ticketClerkLocks[myTicketClerk]);
	/*CVSignal(ticketClerkConditionVariables[myTicketClerk], ticketClerkLocks[myTicketClerk]);
	CVWait(ticketClerkConditionVariables[myTicketClerk], ticketClerkLocks[myTicketClerk]);*/

	/*Pay the clerk*/
	
	ticketClerkLocks[myTicketClerk]->Acquire();
	/*LockAcquire(ticketClerkLocks[myTicketClerk]);*/
	ticketEarnings[myTicketClerk] += ticketsTotal[myTicketClerk];	/*adding the total given by the clerk to the clerk's earnings (simulating paying him)*/
	/*Wait again for clerk's reponse (telling me to leave)*/
	ticketClerkConditionVariables[myTicketClerk]->Signal(ticketClerkLocks[myTicketClerk]);
	ticketClerkConditionVariables[myTicketClerk]->Wait(ticketClerkLocks[myTicketClerk]);
	/*CVSignal(ticketClerkConditionVariables[myTicketClerk], ticketClerkLocks[myTicketClerk]);
	CVWait(ticketClerkConditionVariables[myTicketClerk], ticketClerkLocks[myTicketClerk]);*/
	
	/*Leave the clerk (DON'T ACQUIRE HIS LOCK) and go to the food clerk*/
	
	/*CUSTOMER-FOOD CLERK INTERACTION: GETTING IN LINE - RETURN OF LINE*/
	/*
	Shared Data used here:
		foodClerkLineLock
		foodClerkStates[]
		foodClerkLineCount[]
		foodClerkLineConditionVariables[]
	*/

	/*each mini cust tells the head cust how much food they want*/
	customerConditionVariable[groupNum]->Broadcast(customerLock[groupNum]);
	customerConditionVariable[groupNum]->Wait(customerLock[groupNum]);
	/*CVBroadcast(customerConditionVariable[groupNum], customerLock[groupNum]);
	CVWait(customerConditionVariable[groupNum], customerLock[groupNum]);*/
	
	/*actually buying food (if you need to)*/
	customerLock[groupNum]->Acquire();
	/*LockAcquire(customerLock[groupNum]);*/
	if(popAmount[groupNum] != 0 || sodaAmount[groupNum] != 0) {
		customerLock[groupNum]->Release();
		/*LockRelease(customerLock[groupNum]);*/
		do{
			/*Look at lines and get in shortest one*/
			foodClerkLineLock->Acquire();
			/*LockAcquire(foodClerkLineLock);*/

			/*see if there are any empty lines*/
			for(int i = 0; i < foodClerks; i++) {
				if(foodClerkStates[i] == available) {
					/*Found food clerk that is available (0)*/
					/*Line cannot be shorter so enter line*/
					myFoodClerk = i;
					foodClerkStates[myFoodClerk] = busy;
					break;
				}
			}

			/*holds position of shortest line*/
			int shortestFoodLine = -1;
			/*check if I found an empty line*/
			if(myFoodClerk == -1) {
				/*look for shortest line*/
				int shortestLineLength = 9999;
				for(int i = 0; i < foodClerks; i++ &&  foodClerkStates[i] == busy) {
					if(foodClerkLineCount[i]==0)
					{
						shortestFoodLine = i;
						break;
					}
					if(shortestLineLength > foodClerkLineCount[i]) {
						shortestFoodLine = i;
						shortestLineLength = foodClerkLineCount[i];
					}
				}

				/*must have shortest line at this point*/
				myFoodClerk = shortestFoodLine;
				/*get in that line*/
				foodClerkLineCount[myFoodClerk]++;	/*increment my line's size*/
				printf("Head customer in group %i is getting in Food  Clerk line %i\n",groupNum,myFoodClerk);
				foodClerkLineConditionVariables[myFoodClerk]->Wait(foodClerkLineLock);	/*puts the thread to sleep and waits for a signal from the food clerk when I'm at the front of the line*/
				/*CVWait(foodClerkLineConditionVariables[myFoodClerk], foodClerkLineLock);*/
			}
			else
				foodClerkLineLock->Release();
				/*LockRelease(foodClerkLineLock);*/
			if(foodClerkStates[myFoodClerk]==on_break)
			{
				printf("Head customer of group %i sees food clerk %i is on break and must find new line\n",groupNum,myFoodClerk);
			}
		}while(foodClerkStates[myFoodClerk] == on_break);	/*if clerk goes on break, customer gets broadcast and starts over*/

		

		/*CUSTOMER-FOOD CLERK INTERACTION: BUYING FOOD*/
		/*
		Shared Data used here:
			foodClerkLock[]
			popcornBeingSold[]
			sodaBeingSold[]
			foodClerkConditionVariables[]
		*/

		customerLock[groupNum]->Acquire();
		foodClerkLocks[myFoodClerk]->Acquire();
		/*LockAcquire(customerLock[groupNum]);
		LockAcquire(foodClerkLocks[myFoodClerk]);*/

		/*pass popcorn amount and wake up clerk*/
		popcornBeingSold[myFoodClerk] = popAmount[groupNum];
		customerLock[groupNum]->Release();
		/*LockRelease(customerLock[groupNum]);*/

		/*And now I wait for the clerk's response (waiting for confirmation)*/
		foodClerkConditionVariables[myFoodClerk]->Signal(foodClerkLocks[myFoodClerk]);
		foodClerkConditionVariables[myFoodClerk]->Wait(foodClerkLocks[myFoodClerk]);
		/*CVSignal(foodClerkConditionVariables[myFoodClerk], foodClerkLocks[myFoodClerk]);
		CVWait(foodClerkConditionVariables[myFoodClerk], foodClerkLocks[myFoodClerk]);*/

		foodClerkLocks[myFoodClerk]->Acquire();
		/*LockAcquire(foodClerkLocks[myFoodClerk]);*/

		/*pass soda amount and wake up clerk*/
		sodaBeingSold[myFoodClerk] = sodaAmount[groupNum];
		/*wait for clerk's response (giving me food)*/
		printf("Head customer in group %i is walking up to food clerk %i to order %i popcorn and %i soda\n",groupNum,myFoodClerk,popAmount[groupNum],sodaAmount[groupNum]);

		foodClerkConditionVariables[myFoodClerk]->Signal(foodClerkLocks[myFoodClerk]);
		foodClerkConditionVariables[myFoodClerk]->Wait(foodClerkLocks[myFoodClerk]);
		/*CVSignal(foodClerkConditionVariables[myFoodClerk], foodClerkLocks[myFoodClerk]);
		CVWait(foodClerkConditionVariables[myFoodClerk], foodClerkLocks[myFoodClerk]);*/

		/*should have food by now*/
		hasFood = true;

		/*Pay the clerk*/
		foodClerkLocks[myFoodClerk]->Acquire();
		/*LockAcquire(foodClerkLocks[myFoodClerk]);*/
		foodEarnings[myFoodClerk] += foodTotal[myFoodClerk];	/*adding the total given by the clerk to the clerk's earnings (simulating paying him)*/
		/*Wait again for clerk's reponse (telling me to leave)*/
		printf("Head customer %i is paying %i to food clerk %i\n",groupNum,foodTotal[myFoodClerk],myFoodClerk);

		foodClerkConditionVariables[myFoodClerk]->Signal(foodClerkLocks[myFoodClerk]);
		foodClerkConditionVariables[myFoodClerk]->Wait(foodClerkLocks[myFoodClerk]);
		/*CVSignal(foodClerkConditionVariables[myFoodClerk], foodClerkLocks[myFoodClerk]);
		CVWait(foodClerkConditionVariables[myFoodClerk], foodClerkLocks[myFoodClerk]);*/
		printf("Head customer %i is leaving food clerk %i\n",groupNum,myFoodClerk);
	}
	else
		customerLock[groupNum]->Release();
		/*LockRelease(customerLock[groupNum]);*/


	/*leave the food clerk and go to the ticket clerk*/
	
	/*CUSTOMER-TICKET TAKER INTERACTION: GETTING IN LINE - THE FINAL CHAPTER*/
	/*
	Shared Data used here:
		ticketTakerLineLock
		ticketTakerStates[]
		ticketTakerLineCount[]
		ticketTakerLineConditionVariables[]
	*/
			
	customersServed++;
					
takerLine:
	do{
		/*Look at lines and get in shortest one*/
		ticketTakerLineLock->Acquire();
		/*LockAcquire(ticketTakerLineLock);*/

		/*see if there are any empty lines*/
		for(int i = 0; i < ticketTakers; i++) {
			if(ticketTakerStates[i] == available) {
					
				/*Found ticket taker that is available (0)*/
				/*Line cannot be shorter so enter line*/
				printf("Checking TT\n");
				myTicketTaker = i;
				ticketTakerStates[myTicketTaker] = busy;
				break;
			}
		}
			
		/*holds position of shortest line*/
		int shortestTakerLine = -1;
		/*check if I found an empty line*/
	
		if(myTicketTaker == -1) {
			
			/*look for shortest line*/
			int shortestLineLength = 9999;
			for(int i = 0; i < ticketTakers; i++ && ticketTakerStates[i] == busy) {
				if(ticketTakerLineCount[i]==0)
				{
					shortestTakerLine=i;
					break;
				}
				if(shortestLineLength > ticketTakerLineCount[i]) {
					shortestTakerLine = i;
					shortestLineLength = ticketTakerLineCount[i];
				}
			}

			/*must have shortest line at this point*/
			myTicketTaker = shortestTakerLine;
			/*get in that line*/
			printf("Head Customer in Group %i is getting in TicketTaker line %i\n", groupNum, myTicketTaker);
			ticketTakerLineCount[myTicketTaker]++;	/*increment my line's size*/
			ticketTakerLineConditionVariables[myTicketTaker]->Wait(ticketTakerLineLock);	/*puts the thread to sleep and waits for a signal from the ticket taker when I'm at the front of the line*/
			/*CVWait(ticketTakerLineConditionVariables[myTicketTaker], ticketTakerLineLock);*/
			
		}
		else
			ticketTakerLineLock->Release();
			/*LockRelease(ticketTakerLineLock);*/

	}while(ticketTakerStates[myTicketTaker] == on_break);	/*if clerk goes on break, customer gets broadcast and starts over*/
	/*CUSTOMER-TICKET TAKER INTERACTION: GIVING TICKETS*/
	/*
	Shared Data used here:
		ticketTakerLocks[]
		ticketTakerConditionVariables[]
	*/


	ticketTakerLocks[myTicketTaker]->Acquire();
	/*LockAcquire(ticketTakerLocks[myTicketTaker]);*/

	/*pass number of tickets*/
	numberOfTickets[myTicketTaker] = custSize;
	/*And now I wait for the taker's response (telling me to go in or not)*/
	
	ticketTakerConditionVariables[myTicketTaker]->Signal(ticketTakerLocks[myTicketTaker]);
	ticketTakerConditionVariables[myTicketTaker]->Wait(ticketTakerLocks[myTicketTaker]);
	/*CVSignal(ticketTakerConditionVariables[myTicketTaker], ticketTakerLocks[myTicketTaker]);
	CVWait(ticketTakerConditionVariables[myTicketTaker], ticketTakerLocks[myTicketTaker]);*/

	/*wait or go in depending on if the theater is full*/
	
	ticketTakerLocks[myTicketTaker]->Acquire();
	/*LockAcquire(ticketTakerLocks[myTicketTaker]);*/
	


	if(dontGoIn[myTicketTaker]) {
		ticketTakerConditionVariables[myTicketTaker]->Signal(ticketTakerLocks[myTicketTaker]);
		ticketTakerLocks[myTicketTaker]->Release();
		/*CVSignal(ticketTakerConditionVariables[myTicketTaker], ticketTakerLocks[myTicketTaker]);
		LockRelease(ticketTakerLocks[myTicketTaker]);*/
		
		lobbyCV->Wait(lobbyLock);
		/*CVWait(lobbyCV, lobbyLock);*/
		myTicketTaker=-1;
		goto takerLine;
	}
	ticketTakerConditionVariables[myTicketTaker]->Signal(ticketTakerLocks[myTicketTaker]);
	ticketTakerLocks[myTicketTaker]->Release();
	takingTicketsLock->Release();
	/*CVSignal(ticketTakerConditionVariables[myTicketTaker], ticketTakerLocks[myTicketTaker]);
	LockRelease(ticketTakerLocks[myTicketTaker]);
	LockRelease(takingTicketsLock);*/
		
	/*CUSTOMER-THEATER INTERACTION: SIT YOU DOWN BOY*/
	/*
	Shared Data used here:
		seatsFreeLock
		seats[][]
		seatsFree[]
	*/
	
	/*go into theater*/

	
	seatsFreeLock->Acquire();
	/*LockAcquire(seatsFreeLock);*/
	
	/*find the row with the most seats*/
	int goodRow1 = seatsFree[0];
	int goodRowNumber = 0;
	for(int i = 1; i < 5; i++) {
		if(seatsFree[i] > goodRow1) {
			goodRow1 = seatsFree[i];
			goodRowNumber = i;
		}
	}
	custsSeated++;
	int num = 0;	/*counter*/
	/*look for 5 in a row*/
	for(int i = 5-goodRow1; i < 5; i++) {	/*this is where we get in the seats*/
		if(i==5-goodRow1)
		{
			seats[goodRowNumber][i] = false;
		}
		/*record position*/
		custPositions[groupNum][num][0] = goodRowNumber;
		custPositions[groupNum][num][1] = i;
		num++;

		if(num == custSize) {
			seated = true;
			goto seated;
		}
	}
	
	if(goodRowNumber==4)
	{
		for(int j=1;j<5;j++)
		{
			for(int i = 5-seatsFree[goodRowNumber-j]; i < 5; i++) 
			{	
				/*record position*/
				custPositions[groupNum][num][0] = goodRowNumber-j;
				custPositions[groupNum][num][1] = i;
				num++;

				if(num == custSize) {
					seated = true;
					goto seated;
			}
		}
		}
	}

	else if(goodRowNumber==0)
	{
		for(int j=1;j<5;j++)
		{
			for(int i = 5-seatsFree[goodRowNumber+j]; i < 5; i++) 
			{	
				/*record position*/
				custPositions[groupNum][num][0] = goodRowNumber+j;
				custPositions[groupNum][num][1] = i;
				num++;

				if(num == custSize) {
					seated = true;
					goto seated;
			}
		}
		}
	}

	else
	{
		for(int j=1; j<3; j++)
		{
			if((goodRowNumber-j)>-1)
			{
				for(int i = 5-seatsFree[goodRowNumber-j]; i < 5; i++) 
				{	
					/*record position*/
					custPositions[groupNum][num][0] = goodRowNumber-j;
					custPositions[groupNum][num][1] = i;
					num++;

					if(num == custSize)
					{
						seated = true;
						goto seated;
					}
				}
			}

			if(goodRowNumber+j<5)
			{
				for(int i = 5-seatsFree[goodRowNumber+j]; i < 5; i++) 
				{	
					/*record position*/
					custPositions[groupNum][num][0] = goodRowNumber+j;
					custPositions[groupNum][num][1] = i;
					num++;

					if(num == custSize)
					{
						seated = true;
						goto seated;
					}
				}
			}
		}
			
	}
	

seated:	/*jump to here when you're seated*/
				
	seatedPeople+=custSize;
	customerConditionVariable[groupNum]->Broadcast(customerLock[groupNum]);
	/*CVBroadcast(customerConditionVariable[groupNum], customerLock[groupNum]);*/
	
	/*CUSTOMER-TECH INTERACTION: SHITTY MINISERIES*/
	/*
	Shared Data used here:
		techMovieVariable
	*/

	/*watch movie and wait for it to finish*/
	techMovieVariable->Wait(seatsFreeLock);
	/*CVWait(techMovieVariable, seatsFreeLock);*/
	ticketsTaken--;
	custsSeated--;
	currentThread->Yield();

	int j = rand() % 4;
	if(j==0)
	{
		for(int i = 0; i<50;i++)
		{
			currentThread->Yield();
		}
	}
	
	customerLock[groupNum]->Acquire();
	/*LockAcquire(customerLock[groupNum]);*/

	/*CUSTOMER-THEATER INTERACTION: INCEPTION 2 - GET OUT THE DREAM IS COLLAPSING*/
	/*
	Shared Data used here:
		seats[][]
	*/

	customerConditionVariable[groupNum]->Broadcast(customerLock[groupNum]);
	/*CVBroadcast(customerConditionVariable[groupNum], customerLock[groupNum]);*/

	printf("Head customer in group %i is Leaving the theater\n",groupNum);
	numberOfCustomers--;
	currentThread->Finish();
	}





void MiniCustomer(int IDNums[3]) 
{

	int groupNum = IDNums[0];
	int custNum = IDNums[1];
	int custSize = IDNums[2];

	printf("Customer %i in group %i has entered the theater\n",custNum,groupNum);
	if(custNum>5||custNum<0)
	{
		printf("Cust Num is %i\n",custNum);
	}
	customerConditionVariable[groupNum]->Wait(customerLock[groupNum]);
	/*CVWait(customerConditionVariable[groupNum], customerLock[groupNum]);*/

	customerLock[groupNum]->Acquire();
	/*LockAcquire(customerLock[groupNum]);*/
	bool popcorn=0;
	bool soda=0;
	/*determine how much popcorn and soda to buy using randomness*/
	int j = rand() % 100;
	if(j < 75) {
		popAmount[groupNum]++;
		popcorn=true;
	}
	j = rand() % 100;
	if(j < 75) {
		sodaAmount[groupNum]++;
		soda=true;
	}

	printf("Customer %i in group %i wants %i popcorn and %i soda\n",custNum,groupNum,popcorn,soda);

	foodReportCount[groupNum]++;
	if(foodReportCount[groupNum] == custSize-1) {
		/*release that food lock I'm holding and go back to sleep*/
		customerConditionVariable[groupNum]->Signal(customerLock[groupNum]);
		/*CVSignal(customerConditionVariable[groupNum], customerLock[groupNum]);*/
	}
	customerConditionVariable[groupNum]->Wait(customerLock[groupNum]);
	/*CVWait(customerConditionVariable[groupNum], customerLock[groupNum]);*/


	seatsFreeLock->Acquire();
	customerLock[groupNum]->Acquire();
	/*LockAcquire(seatsFreeLock);
	LockAcquire(customerLock[groupNum]);*/
	
	printf("Customer %i in group %i is sitting in a seat\n",custNum,groupNum);
	seats[custPositions[groupNum][custNum][0]][custPositions[groupNum][custNum][1]] = false;
	custsSeated++;
	
	customerLock[groupNum]->Release();
	techMovieVariable->Wait(seatsFreeLock);
	/*LockRelease(customerLock[groupNum]);
	CVWait(techMovieVariable, seatsFreeLock);*/
	

	/*get out of your seats*/
	printf("Customer %i in group %i is getting out of his seat\n",custNum,groupNum);
	seats[custPositions[groupNum][custNum][0]][custPositions[groupNum][custNum][1]] = true;
	ticketsTaken--;
	custsSeated--;

	

	j = rand() % 4;
	if(j==0)
	{
		printf("%s %i is going to bathroom\n",currentThread->getName(),groupNum);
		customerLock[groupNum]->Acquire();
		/*LockAcquire(customerLock[groupNum]);*/

		//custsInBathroom[groupNum]++;
		//customerLock[groupNum]->Release();
		/*for(int i = 0; i<50;i++)
		{
			currentThread->Yield();
		}*/
		//customerLock[groupNum]->Acquire();
		//custsInBathroom[groupNum]--;
		
		if(custsInBathroom[groupNum]==0)
		{
			headCustomerCondition[groupNum]->Signal(customerLock[groupNum]);
			/*CVSignal(headCustomerCondition[groupNum], customerLock[groupNum]);*/
		}
	}
	customerConditionVariable[groupNum]->Wait(customerLock[groupNum]);
	/*CVWait(customerConditionVariable[groupNum], customerLock[groupNum]);*/
	currentThread->Finish();
}
